package com.eternal.control;

import android.annotation.SuppressLint;
import android.app.Application;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.paging.PagedList;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.view.View;

import com.eternal.base.concat.DeviceMinModel;
import com.eternal.base.concat.DeviceModel;
import com.eternal.base.data.DeviceRepository;
import com.eternal.base.data.ble.BleStatue;
import com.eternal.base.global.ActivityEvent;
import com.eternal.base.global.BluetoothKey;
import com.eternal.base.global.ProgressEvent;
import com.eternal.framework.bus.RxBus;
import com.eternal.framework.component.BaseViewModel;
import com.eternal.framework.utils.KLog;
import com.eternal.framework.utils.RxUtils;

import org.reactivestreams.Publisher;

import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.http.HEAD;

/**
 * Created by Administrator
 * On 2020/5/4
 * Description:
 *
 * @author Administrator
 */
public class ControlModel extends BaseViewModel {
    public ControlModel(@NonNull Application application) {
        super(application);
        expand.setValue(false);
    }

    private DeviceRepository repository;
    public DeviceModel info,lastInfo;
    private String mac;
    private byte port;
    private Disposable refresh;
    public boolean isRefreshComplete;

    public MutableLiveData<Boolean> expand = new MutableLiveData<>();
    public MutableLiveData<String> model = new MutableLiveData<>();
    public MutableLiveData<String> show = new MutableLiveData<>();
    public MutableLiveData<Byte> cycleModel = new MutableLiveData<>();
    public MutableLiveData<Boolean> controlTypeByHumModel =new MutableLiveData<>();

    public boolean refreshStopped;

    public View.OnClickListener onModel = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (expand.getValue().equals(Boolean.TRUE)) {
                expand.postValue(false);
            } else {
                expand.postValue(true);
            }
        }
    };

    public View.OnClickListener onReModel = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            changeModel(v.getId());
            expand.setValue(false);
        }
    };

    private void changeModel(int id) {
        cancelUpdate();
        if (id == R.id.txt_mode_off) {
            sendModel(BluetoothKey.MODE_OFF);
        } else if (id == R.id.txt_mode_on) {
            sendModel(BluetoothKey.MODE_ON);
        } else if (id == R.id.txt_mode_auto) {
            sendModel(BluetoothKey.MODE_AUTO);
        } else if (id == R.id.txt_mode_time_to_on) {
            sendModel(BluetoothKey.MODE_TIME_ON);
        } else if (id == R.id.txt_mode_time_to_off) {
            sendModel(BluetoothKey.MODE_TIME_OFF);
        } else if (id == R.id.txt_mode_cycle) {
            sendModel(BluetoothKey.MODE_CYCLE);
        } else if (id == R.id.txt_mode_sched) {
            sendModel(BluetoothKey.MODE_SCHED);
        }
    }

    @SuppressLint("CheckResult")
    public void init(final DeviceRepository repository, final String mac,byte port) {
        this.repository = repository;
        this.mac = mac;
        this.port = port;
        Disposable disposable = repository.getModel(mac,port)
                .compose(RxUtils.<DeviceModel>bindToLifecycle(getLifecycleProvider()))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        if (repository.isConnect(mac)) {
                            RxBus.getDefault().post(new ProgressEvent(ProgressEvent.START));
                        }
                    }
                })
                .subscribe(new Consumer<DeviceModel>() {
                    @Override
                    public void accept(DeviceModel model) {
                        ControlModel.this.info = model;
                        //发送消息到AdvanceModel
                        RxBus.getDefault().post(new ActivityEvent(ActivityEvent.SET_DEVICE_MODEL_INFO, model));
                        cycleModel.setValue(model.workType);
                        controlTypeByHumModel.setValue(model.isControlTypeByHum);
                        if (repository.isConnect(mac)) {
                            RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
                        }
                        start();
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        throwable.printStackTrace();
                        KLog.e(throwable);
                    }
                });
        addSubscribe(disposable);
    }

    public void onPause() {
        stop();
    }

    public void onResume() {
        if (repository.isConnect(mac)) {
            start();
        }
    }

    @SuppressLint("CheckResult")
    public void sendModel(byte model) {
        BleStatue statue = repository.getConnect(mac);
        if (statue != null) {
            repository.setModel(statue,port, model)
                    .compose(RxUtils.<Boolean>bindToLifecycle(getLifecycleProvider()))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Boolean>() {
                        @Override
                        public void accept(Boolean result) {
                            RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
                            start();
                            if (!result) {
                                KLog.e("set model error");
                            }
                        }
                    }, new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable throwable) throws Exception {
                            start();
                            throwable.printStackTrace();
                            KLog.e(throwable);
                        }
                    });
        } else {
            cycleModel.setValue(model);
        }
    }

    public void cancelUpdate() {
        if (repository.isConnect(mac)) {
            RxBus.getDefault().post(new ProgressEvent(ProgressEvent.START));
        }
        stop();
    }

    @SuppressLint("CheckResult")
    public void sendData() {
        final BleStatue statue = repository.getConnect(mac);
        if (statue != null) {
            refreshStopped = false;
            repository.setModel(statue, port, info)
                    .compose(RxUtils.<Boolean>bindToLifecycle(getLifecycleProvider()))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Boolean>() {
                        @Override
                        public void accept(Boolean aBoolean) throws Exception {
                            RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
                            start();
                        }
                    }, new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable throwable) throws Exception {
//                            throwable.printStackTrace();
                            KLog.e(throwable);
                        }
                    });
        }
    }

    @SuppressLint("CheckResult")
    public void save() {
        if (repository.isConnect(mac)) {
            repository.saveModel(mac, port, info).subscribeOn(Schedulers.io()).subscribe();
        }
    }

    private void updateInfo(DeviceMinModel model) {
        lastInfo = info.clone();

        info.isDegree = model.isDegree;
        info.workType = model.model;
        info.tmp = model.tmp;
        info.hum = model.per;
        info.fan = model.fan;
        info.fanState = model.fanState;
        info.humState = model.humState;
        info.tmpState = model.tmpState;
        switch (model.model) {
            case BluetoothKey.MODE_OFF:
                info.typeOff = model.getFan();
                break;
            case BluetoothKey.MODE_ON:
                info.typeOn = model.getFan();
                break;
            case BluetoothKey.MODE_AUTO:
                info.autoHighTmpSwitch = model.hTmpSwitch();
                info.autoLowTmpSwitch = model.lTmpSwitch();
                info.autoHighTmp = model.getHighTmp();
                info.autoLowTmp = model.getLowTmp();
                info.autoHighHumSwitch = model.hHumSwitch();
                info.autoLowHumSwitch = model.lHumSwitch();
                info.autoHighHum = model.getHighHum();
                info.autoLowHum = model.getLowHum();
                break;
            case BluetoothKey.MODE_TIME_ON:
                info.timeOn = model.getTime();
                info.currentTypeResidueTime = (int) model.time.time;
                info.currentTypeResidueOn = !model.time.isOff;
                break;
            case BluetoothKey.MODE_TIME_OFF:
                info.timeOff = model.getTime();
                info.currentTypeResidueTime = (int) model.time.time;
                info.currentTypeResidueOn = !model.time.isOff;
                break;
            case BluetoothKey.MODE_CYCLE:
                info.cycleOn = model.getOn();
                info.cycleOff = model.getOff();
                info.currentTypeResidueTime = (int) model.time.time;
                info.currentTypeResidueOn = !model.time.isOff;
                break;
            default:
                info.schedOn = model.getStart();
                info.schedOff = model.getEnd();
        }
    }

    public void setControlTypeByHum(boolean isControlTypeByHum) {
        repository.setControlTypeByHum(mac, port,isControlTypeByHum)
                .compose(RxUtils.bindToLifecycle(getLifecycleProvider()))
                .subscribeOn(Schedulers.io())
                .subscribe();
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void start() {
        refreshStopped = false;
        BleStatue statue = repository.getConnect(mac);
        if (statue != null) {
            if (refresh == null) {
                KLog.i("control refresh start");
                refresh = repository.getModel(statue,port)
                        .compose(RxUtils.<DeviceMinModel>bindToLifecycle(getLifecycleProvider()))
                        .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                        .repeatWhen(new Function<Flowable<Object>, Publisher<?>>() {
                            @Override
                            public Publisher<?> apply(Flowable<Object> objectFlowable) throws Exception {
                                return objectFlowable.delay(1, TimeUnit.SECONDS);
                            }
                        })
                        .subscribe(new Consumer<DeviceMinModel>() {
                            @Override
                            public void accept(DeviceMinModel model) {
                                updateInfo(model);
                                cycleModel.setValue(model.model);
                                isRefreshComplete = true;
                            }
                        }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) throws Exception {
                                throwable.printStackTrace();
                                KLog.e(throwable);
                                isRefreshComplete = true;
                            }
                        });
            }
        } else {
            isRefreshComplete = true;
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void stop() {
        if (refresh != null) {
            KLog.e("control refresh end ");
            refresh.dispose();
            refresh = null;
        }
        refreshStopped = true;
    }

    public void register() {
        addSubscribe(RxBus.getDefault()
                .toObservable(ActivityEvent.class)
                .subscribe(new Consumer<ActivityEvent>() {
                    @Override
                    public void accept(ActivityEvent event) throws Exception {
                        if (event.what == ActivityEvent.SET_DEVICE_MODEL_INFO_DEGREE) {
                            DeviceModel info = (DeviceModel) event.obj;
                            if (info != null) {
                                KLog.e("ControlModel : " + info.isDegree);
                                ControlModel.this.info.isDegree = info.isDegree;
                                onResume();
                            }
                        }
                    }
                }));
    }
}
